/**
 * 
 */
package com.goktech.commons.excel.utils.writer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Map;

import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.goktech.commons.excel.ExcelException;
import com.goktech.commons.excel.ExcelFileTemp;
import com.goktech.commons.excel.ExcelStyleResolver;
import com.goktech.commons.excel.RowFactory;
import com.goktech.commons.excel.utils.abs.AbstractExcelWriter;
import com.goktech.commons.utils.StringUtils;

/**
 * @author 24252
 *
 */
public class ExceltBigDataExport extends AbstractExcelWriter<ExceltBigDataExport> {

	private SXSSFWorkbook sxssfWorkbook;

	private int sheetIndex = 0;

	private ExcelFileTemp excelFileTemp;


	public ExceltBigDataExport(Class<?> clazz) {
		super(clazz);
	}
	
	public ExceltBigDataExport(Class<?> clazz,String path,String firstSheetName,int rowAccessWindowSize) {
		super(clazz);
		initTmpFile(path, null,firstSheetName,rowAccessWindowSize);
	}
	
	/**
	 * 
	 * @param clazz
	 * @param apth
	 */
	public ExceltBigDataExport(Class<?> clazz, String path) {
		this(clazz);
		initTmpFile(path, null,"临时表",1000);
	}

	public ExceltBigDataExport(Class<?> clazz, String path, Map<String, Object> data) {
		this(clazz);
		initTmpFile(path, data,"临时表",1000);
	}

	public void initTmpFile(String path, Map<String, Object> data,String firstSheetName,int rowAccessWindowSize) {
		try {
			createExcel(path,firstSheetName,data,rowAccessWindowSize);
		} catch (ExcelException | IOException e) {
			if (excelFileTemp != null) {
				excelFileTemp.clear();
			}
			e.printStackTrace();
		}
	}

	@Override
	protected void setSummaryInformatioin() {

	}

	/**
	 * 初始化自定义的行
	 */
	@Override
	public ExceltBigDataExport initRows() {
		RowFactory factory = new RowFactory(this.getLastRowsList(), sheet, this.sxssfWorkbook);
		if(excelStyle != null){
			factory.setExcelStyle(excelStyle);
		}
		factory.create();
		this.rowIndex = factory.getRowIndex();
		if (logger.isDebugEnabled())
			logger.debug("initRows success end rowIndex -> {}", this.rowIndex);
		return this.getSelf();
	}

	/**
	 * 初始化定义的行，可以携带定义参数
	 * @param data
	 * @return
	 */
	public ExceltBigDataExport initRows(Map<String,Object> data) {
		RowFactory factory = new RowFactory(this.getLastRowsList(), sheet, this.sxssfWorkbook,data);
		if(excelStyle != null){
			factory.setExcelStyle(excelStyle);
		}
		factory.create();
		this.rowIndex = factory.getRowIndex();
		if (logger.isDebugEnabled())
			logger.debug("initRows success end rowIndex -> {}", this.rowIndex);
		return this.getSelf();
	}
	
	@Override
	public ExceltBigDataExport initTitle() {
		if (this.paramsList.size() == 0) {
			getProperty();
		}
		String title = null;
		SXSSFRow row = (SXSSFRow) createRow(rowIndex);
		for (int i = 0; i < this.paramsList.size(); i++) {
			SXSSFCell cell = (SXSSFCell) createCell(row, i);
			if (cell != null) {
				title = this.excelMap.get(paramsList.get(i)).name();
				cell.setCellValue(StringUtils.isEmpty(title) ? this.paramsList.get(i) : title);
			} else {
				logger.error("SXSSFCell is null");
			}
			if (excelStyle != null)
				cell.setCellStyle(excelStyle.getTitleStyle(this.paramsList.get(i)));
		}
		
		if (logger.isDebugEnabled())
			logger.debug("title init success size:{}", this.paramsList.size());
		return this.getSelf();
	}

//	@Override
//	public ExceltBigDataExport forEach(Collection<?> collection) {
//		if (this.paramsList.size() == 0) {
//			getProperty();
//		}
//		if (logger.isDebugEnabled()) {
//			logger.debug("当前导出数据的总数：{}", collection == null ? 0 : collection.size());
//		}
//		for (Iterator<?> it = collection.iterator(); it.hasNext();) {
//			Row row = this.createRow(rowIndex);
//			Object obj = it.next();
//			for (int i = 0; i < paramsList.size(); i++) {
//				Cell cell = createCell(row, i);
//				if (obj == null) {
//					cell.setCellValue(this.excelMap.get(this.paramsList.get(i)).defaultValue());
//				} else {
//					Object value = propertyUtils.getCacheProperty(obj, paramsList.get(i));
//					ValueSelector.getValue(value, cell, this.excelMap.get(this.paramsList.get(i)));
//				}
//			}
//		}
//		return this.getSelf();
//	}

	@Override
	public ExceltBigDataExport createSheet(String name) {
		// TODO 多工作薄导出带开发
		if (StringUtils.isEmpty(name)) {
			name = "工作薄-" + sheetIndex;
			;
		}
		if (sheetIndex == 0) {
			this.sheet = this.sxssfWorkbook.getSheetAt(sheetIndex++);
		} else {
			this.sheet = this.sxssfWorkbook.createSheet(name);
		}
		return this.getSelf();
	}

	/**
	 *  一键初始化自定义的行和表头
	 * @param data
	 * @return
	 */
	public ExceltBigDataExport ReInit() {
		// 初始化自定义行
		initRows();
		// 初始化表头
		initTitle();
		return this;
	}

	/**
	 * 一键初始化自定义的行和表头
	 * @param data
	 * @return
	 */
	public ExceltBigDataExport ReInit(Map<String, Object> data) {
		// 初始化自定义行
		initRows(data);
		// 初始化表头
		initTitle();
		return this;
	}
	
	@Override
	public void write(OutputStream outputStream) throws IOException {
		try {
			this.sxssfWorkbook.write(outputStream);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (excelFileTemp != null) {
				excelFileTemp.clear();
			}
		}
	}

	private ExceltBigDataExport createExcel(String path,String sheetName,Map<String,Object> data,int rowAccessWindowSize) throws ExcelException, IOException{
		excelFileTemp = new ExcelFileTemp(path);
		// 临时文件初始化表头
		ExcelXSSFExport export = new ExcelXSSFExport(clazz, data).createSheet("临时表格").initTitle().forEach(new ArrayList<>());
		export.write(excelFileTemp.getOutputStream());
		this.rowIndex = export.getRowIndex();
		InputStream fi = excelFileTemp.getStream();
		this.sxssfWorkbook = new SXSSFWorkbook(new XSSFWorkbook(fi), rowAccessWindowSize);
		return this.getSelf();
	}
	
	@Override
	public ExceltBigDataExport getSelf() {
		return this;
	}

	@Override
	public ExceltBigDataExport initStyle() {
		excelStyle = new ExcelStyleResolver(clazz, this.sxssfWorkbook);
		return this.getSelf();
	}

	@Override
	public Workbook workbook() {
		return this.sxssfWorkbook;
	}
}
